package com.anycc.cloud.common.dto.easyui;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * easyui tree build
 */
public abstract class TreeBuilder<T> {
    private String[] checkedNodeIds;

    public TreeBuilder() {
    }

    protected abstract T getParent(T var1);

    protected abstract List<T> getChildren(T var1);

    protected abstract String getNodeId(T var1);

    protected abstract String getNodeText(T var1);

    protected void addExtraInfo(Tree treeNode, T entity) {
    }

    protected Tree buildTreeNode(String id, String text) {
        Tree treeNode = new Tree(id, text);
        if (this.checkedNodeIds != null) {
            this.initTreeNodeChecked(treeNode, this.checkedNodeIds);
        }
        return treeNode;
    }

    private Tree buildTreeNode(T entity, List<T> childEntityList, boolean hasExtraInfo, String... checkedNodeIds) {
        Tree treeNode = new Tree(this.getNodeId(entity), this.getNodeText(entity));
        this.initTreeNodeChecked(treeNode, this.checkedNodeIds);
        if (hasExtraInfo) {
            this.addExtraInfo(treeNode, entity);//工厂方法模式添加额外信息
        }
        if (!this.getChildren(entity).isEmpty()) {//递归添加子节点
            childEntityList.forEach(t -> {
                if (this.getParent(t) != null && StringUtils.equals(getNodeId(entity), getNodeId(this.getParent(t)))) {
                    Tree treeChildNode = this.buildTreeNode(t, childEntityList, hasExtraInfo, checkedNodeIds);//recursion
                    treeNode.getChildren().add(treeChildNode);
                }
            });
        }
        return treeNode;
    }


    public List<Tree> buildTreeList(List<T> entityList, String... checkedNodeIds) {
        return this.buildTreeList(entityList, false, checkedNodeIds);
    }

    public List<Tree> buildTreeList(List<T> entityList, boolean hasExtraInfo, String... checkedNodeIds) {
        this.checkedNodeIds = checkedNodeIds;
        List<Tree> treeList = new ArrayList<>();
        List<T> rootEntityList = new ArrayList<>();
        List<T> childEntityList = new ArrayList<>();
        this.filterEntityList(entityList, rootEntityList, childEntityList, null);
        if (!rootEntityList.isEmpty()) {
            rootEntityList.forEach(t ->
                    treeList.add(this.buildTreeNode(t, childEntityList, hasExtraInfo, checkedNodeIds))
            );
        }

        return treeList;
    }

    public List<Tree> buildParentTreeList(List<T> entityList, T currentEntity) {
        return this.buildParentTreeList(entityList, currentEntity, false);
    }

    public List<Tree> buildParentTreeList(List<T> entityList, T currentEntity, boolean hasExtraInfo) {
        List<Tree> treeList = new ArrayList<>();
        List<T> rootEntityList = new ArrayList<>();
        List<T> childEntityList = new ArrayList<>();
        filterEntityList(entityList, rootEntityList, childEntityList, currentEntity);
        if (!rootEntityList.isEmpty()) {
            if (getParent(currentEntity) != null) {
                checkedNodeIds = new String[]{getNodeId(getParent(currentEntity))};
                rootEntityList.forEach(rootEntity ->
                        treeList.add(buildTreeNode(rootEntity, childEntityList, hasExtraInfo, checkedNodeIds))
                );
            } else {
                rootEntityList.forEach(rootEntity ->
                        treeList.add(buildTreeNode(rootEntity, childEntityList, hasExtraInfo))
                );
            }
        }

        return treeList;
    }


    /**
     * 分离父元素和子元素
     *
     * @param entityList      实例集合
     * @param rootEntityList  根集合
     * @param childEntityList 子集集合
     * @param excludeEntity   排除元素
     */
    private void filterEntityList(List<T> entityList, List<T> rootEntityList, List<T> childEntityList, T excludeEntity) {
        Iterator<T> iterator = entityList.iterator();

        while (true) {
            T entity;
            //排除不需要的实体元素
            do {
                if (!iterator.hasNext()) {
                    return;
                }
                entity = iterator.next();
            } while (excludeEntity != null && StringUtils.equals(this.getNodeId(entity), this.getNodeId(excludeEntity)));

            if (this.getParent(entity) == null) {
                rootEntityList.add(entity);
            } else {
                childEntityList.add(entity);
            }
        }

    }

    /**
     * 初始化节点选中状态
     *
     * @param treeNode       treeNode
     * @param checkedNodeIds checkedNodeIds
     */
    private void initTreeNodeChecked(Tree treeNode, String... checkedNodeIds) {
        if (checkedNodeIds != null) {
            Arrays.stream(checkedNodeIds).forEach(checkedNodeId -> {
                if (StringUtils.equals(treeNode.getId(), checkedNodeId)) {
                    treeNode.setChecked(Boolean.TRUE);
                }
            });
        }
    }
}

